﻿using Duende.IdentityServer.Extensions;
using Duende.IdentityServer.Models;
using Duende.IdentityServer.Stores;
using Service.Auth.Domain.AggregatesModel;
using Service.Core.Repository;
using Service.Repository;
using SqlSugar;

namespace Service.Auth.Api.Extensions
{
    /// <summary>
    /// 
    /// </summary>
    /// <param name="persistedGrantRepository"></param>
    public class MysqlPersistedGrantStore(IRepository<TPersistedGrant> persistedGrantRepository) : IPersistedGrantStore
    {
        public async Task<IEnumerable<PersistedGrant>> GetAllAsync(PersistedGrantFilter filter)
        {
            var persistedGrants = await persistedGrantRepository.GetListAsync();

            return persistedGrants.Select(persistedGrant => new PersistedGrant
            {
                Key = persistedGrant.Key,
                Type = persistedGrant.Type,
                SubjectId = persistedGrant.SubjectId,
                SessionId = persistedGrant.SessionId,
                ClientId = persistedGrant.ClientId,
                CreationTime = persistedGrant.CreationTime,
                Expiration = persistedGrant.Expiration,
                Data = persistedGrant.Data
            });
        }

        public async Task<PersistedGrant?> GetAsync(string key)
        {
            var persistedGrant = await persistedGrantRepository.GetByIdAsync(key);
            if (persistedGrant == null)
            {
                return null;
            }
            return new PersistedGrant
            {
                Key = persistedGrant.Key,
                Type = persistedGrant.Type,
                SubjectId = persistedGrant.SubjectId,
                SessionId = persistedGrant.SessionId,
                ClientId = persistedGrant.ClientId,
                CreationTime = persistedGrant.CreationTime,
                Expiration = persistedGrant.Expiration,
                Data = persistedGrant.Data
            };
        }

        public async Task RemoveAllAsync(PersistedGrantFilter filter)
        {
            var exp = Expressionable.Create<TPersistedGrant>()
                 .AndIF(!string.IsNullOrWhiteSpace(filter.SubjectId), s => s.SubjectId.Equals(filter.SubjectId))
                 .AndIF(!string.IsNullOrWhiteSpace(filter.SessionId), s => s.SessionId.Equals(filter.SessionId))
                 .AndIF(!string.IsNullOrWhiteSpace(filter.ClientId), s => s.ClientId.Equals(filter.ClientId))
                 .AndIF(!string.IsNullOrWhiteSpace(filter.Type), s => s.Type.Equals(filter.Type))
                 .AndIF(!filter.ClientIds.IsNullOrEmpty(), s => filter.ClientIds.Contains(s.ClientId))
                 .AndIF(!filter.Types.IsNullOrEmpty(), s => filter.Types.Contains(s.Type));
            await persistedGrantRepository.DeleteAsync(exp.ToExpression());
        }

        public async Task RemoveAsync(string key)
        {
            await persistedGrantRepository.DeleteAsync(s => s.Key.Equals(key));
        }

        public async Task StoreAsync(PersistedGrant grant)
        {
            await persistedGrantRepository.InsertAsync(new TPersistedGrant(grant.Key, grant.Type, grant.SubjectId, grant.SessionId, grant.ClientId, grant.Description, grant.CreationTime, grant.Expiration, grant.ConsumedTime, grant.Data));
        }
    }
}